package com.topvision.utils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpClientUtil {

    /**
     * 使用httpclient进行调用
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
     *
     * @param url      访问地址
     * @param paramMap 参数
     * @return 結果
     */
    public static String getPostResult(String url, Map<String, Object> paramMap) {
        // 创建默认的httpClient实例.
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // 创建httppost
        HttpPost httppost = new HttpPost(url);
        httppost.addHeader("accept", "json");
        httppost.addHeader("content_type", "json");

        // 4.3版本不设置超时的话，一旦服务器没有响应，等待时间N久(>24小时)。容易出现504错误（gateway timeout）
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000) // 设置请求和传输超时时间
                .setConnectTimeout(5000).build();
        httppost.setConfig(requestConfig);

        // 增加自定义HEADER,注意：使用addHeader而不是setHeader
/*		if (headerMap != null && !headerMap.isEmpty()) {
            for (String key : headerMap.keySet()) {
				httppost.addHeader(key, headerMap.get(key));
			}
		}
*/
        // 创建参数队列
        List<NameValuePair> paramList = null;
        if (paramMap != null && !paramMap.isEmpty()) {
            paramList = new ArrayList<NameValuePair>();
            for (String key : paramMap.keySet()) {
                paramList.add(new BasicNameValuePair(key, String.valueOf(paramMap.get(key))));
            }
        }
        try {
            if (paramList != null && !paramList.isEmpty()) {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "UTF-8");
                httppost.setEntity(entity);
            }

            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                int status = response.getStatusLine().getStatusCode();

                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");

                // 状态码为200时，才返回正常内容
                if (/*status == HttpStatus.SC_OK && */entity != null) {
                    return result;
                }
                System.out.println("POST请求接口信息出错！" + "请求URL:" + url + "==状态码：==" + status + "==返回结果：==" + result);
            } finally {
                response.close();
            }
        } catch (UnsupportedEncodingException e) {
            System.out.println("参数转码错误！" + e);
        } catch (IOException e) {
            System.out.println("获取httpclient错误！" + e);
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                System.out.println("关闭httpclient失败！" + e);
            }
        }
        return null;
    }

    /**
     * 使用httpclient进行调用
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
     *
     * @param url      访问地址
     * @param paramMap 参数
     * @return 結果
     */
    public static String getZwanPostResult(String url, Map<String, Object> paramMap) {
        // 创建默认的httpClient实例.
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // 创建httppost
        HttpPost httppost = new HttpPost(url);
       /* httppost.addHeader("accept", "json");
        httppost.addHeader("content_type", "json");*/

        // 4.3版本不设置超时的话，一旦服务器没有响应，等待时间N久(>24小时)。容易出现504错误（gateway timeout）
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000) // 设置请求和传输超时时间
                .setConnectTimeout(5000).build();
        httppost.setConfig(requestConfig);

        // 增加自定义HEADER,注意：使用addHeader而不是setHeader
/*		if (headerMap != null && !headerMap.isEmpty()) {
            for (String key : headerMap.keySet()) {
				httppost.addHeader(key, headerMap.get(key));
			}
		}
*/
        // 创建参数队列
        List<NameValuePair> paramList = null;
        if (paramMap != null && !paramMap.isEmpty()) {
            paramList = new ArrayList<NameValuePair>();
            for (String key : paramMap.keySet()) {
                paramList.add(new BasicNameValuePair(key, String.valueOf(paramMap.get(key))));
            }
        }
        try {
            if (paramList != null && !paramList.isEmpty()) {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "UTF-8");
                httppost.setEntity(entity);
            }

            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                int status = response.getStatusLine().getStatusCode();

                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");

                // 状态码为200时，才返回正常内容
                if (/*status == HttpStatus.SC_OK && */entity != null) {
                    return result;
                }
                System.out.println("POST请求接口信息出错！" + "请求URL:" + url + "==状态码：==" + status + "==返回结果：==" + result);
            } finally {
                response.close();
            }
        } catch (UnsupportedEncodingException e) {
            System.out.println("参数转码错误！" + e);
        } catch (IOException e) {
            System.out.println("获取httpclient错误！" + e);
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                System.out.println("关闭httpclient失败！" + e);
            }
        }
        return null;
    }


    /**
     * 使用httpclient进行调用
     * <p>
     * 发送 GET请求访问本地应用并根据传递参数不同返回不同结果
     *
     * @param url      地址
     * @param paramMap 参数
     * @return 结果
     */
    public static String getGetResult(String url, Map<String, Object> paramMap) {
        // 创建参数队列
        StringBuilder sbUrl = new StringBuilder(url).append("?");
        if (paramMap != null && !paramMap.isEmpty()) {
            for (String key : paramMap.keySet()) {
                sbUrl.append(key).append("=").append(paramMap.get(key)).append("&");
            }
        }
        sbUrl.deleteCharAt(sbUrl.length() - 1);

        // 创建默认的httpClient实例.
        CloseableHttpClient httpclient = HttpClients.createDefault();
        // 创建httpget
        HttpGet httpget = new HttpGet(sbUrl.toString());
        httpget.addHeader("accept", "json");
        httpget.addHeader("Content-Type", "json");
        // 4.3版本不设置超时的话，一旦服务器没有响应，等待时间N久(>24小时)。容易出现504错误（gateway timeout）
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000) // 设置请求和传输超时时间
                .setConnectTimeout(10000).build();
        httpget.setConfig(requestConfig);

        try {
            CloseableHttpResponse response = httpclient.execute(httpget);
            response.addHeader("Content-Type", "application/json;charset=UTF-8");
            try {
                int status = response.getStatusLine().getStatusCode();
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");
                // 状态码为200时，才返回正常内容
                if (status == HttpStatus.SC_OK && entity != null) {
                    return result;
                }
                System.out.println("GET请求接口信息出错！" + "请求URL:" + url + "==状态码：==" + status + "==返回结果：==" + result);
            } finally {
                response.close();
            }
        } catch (IOException e) {
            System.out.println("获取httpclient错误！" + e);
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                System.out.println("关闭httpclient失败！" + e);
            }
        }
        return null;
    }

    public static CloseableHttpClient createSSLClientDefault(){
        try {
            SSLContext sslContext=new SSLContextBuilder().loadTrustMaterial(
                    null,new TrustStrategy() {
                        //信任所有
                        @Override
                        public boolean isTrusted(X509Certificate[] chain, String authType)
                                throws CertificateException {
                            return true;
                        }
                    }).build();
            SSLConnectionSocketFactory sslsf=new SSLConnectionSocketFactory(sslContext);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }


    /**
     * 使用httpclient进行调用
     * <p>
     * 发送 GET请求访问本地应用并根据传递参数不同返回不同结果
     *
     * @param url      地址
     * @param paramMap 参数
     * @return 结果
     */
    public static String getHttpsGetResult(String url, Map<String, Object> paramMap) {
        // 创建参数队列
        StringBuilder sbUrl = new StringBuilder(url).append("?");
        if (paramMap != null && !paramMap.isEmpty()) {
            for (String key : paramMap.keySet()) {
                sbUrl.append(key).append("=").append(paramMap.get(key)).append("&");
            }
        }
        sbUrl.deleteCharAt(sbUrl.length() - 1);

        // 创建默认的httpClient实例.
        CloseableHttpClient httpclient = createSSLClientDefault();
        // 创建httpget
        HttpGet httpget = new HttpGet(sbUrl.toString());
        /*httpget.addHeader("accept", "json");
        httpget.addHeader("Content-Type", "json");*/
        // 4.3版本不设置超时的话，一旦服务器没有响应，等待时间N久(>24小时)。容易出现504错误（gateway timeout）
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000) // 设置请求和传输超时时间
                .setConnectTimeout(10000).build();
        httpget.setConfig(requestConfig);

        try {
            CloseableHttpResponse response = httpclient.execute(httpget);
            response.addHeader("Content-Type", "application/json;charset=UTF-8");
            try {
                int status = response.getStatusLine().getStatusCode();
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");
                // 状态码为200时，才返回正常内容
                if (status == HttpStatus.SC_OK && entity != null) {
                    return result;
                }
                System.out.println("GET请求接口信息出错！" + "请求URL:" + url + "==状态码：==" + status + "==返回结果：==" + result);
            } finally {
                response.close();
            }
        } catch (IOException e) {
            System.out.println("获取httpclient错误！" + e);
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                System.out.println("关闭httpclient失败！" + e);
            }
        }
        return null;
    }


    /**
     * 使用httpclient进行调用
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
     *
     * @param url      访问地址
     * @param paramMap 参数
     * @return 結果
     */
    public static String getHttpsPostResult(String url, Map<String, Object> paramMap,Map<String, Object> headerMap) {
        // 创建默认的httpClient实例.
        CloseableHttpClient httpclient = createSSLClientDefault();
        // 创建httppost
        HttpPost httppost = new HttpPost(url);

        // 4.3版本不设置超时的话，一旦服务器没有响应，等待时间N久(>24小时)。容易出现504错误（gateway timeout）
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000) // 设置请求和传输超时时间
                .setConnectTimeout(10000).build();
        httppost.setConfig(requestConfig);

        // 增加自定义HEADER,注意：使用addHeader而不是setHeader
		if (headerMap != null && !headerMap.isEmpty()) {
            for (String key : headerMap.keySet()) {
				httppost.addHeader(key, String.valueOf(headerMap.get(key)));
			}
		}
        // 创建参数队列
        List<NameValuePair> paramList = null;
        if (paramMap != null && !paramMap.isEmpty()) {
            paramList = new ArrayList<NameValuePair>();
            for (String key : paramMap.keySet()) {
                paramList.add(new BasicNameValuePair(key, String.valueOf(paramMap.get(key))));
            }
        }
        try {
            if (paramList != null && !paramList.isEmpty()) {
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "UTF-8");
                httppost.setEntity(entity);
            }

            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                int status = response.getStatusLine().getStatusCode();

                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");

                // 状态码为200时，才返回正常内容
                if (/*status == HttpStatus.SC_OK && */entity != null) {
                    return result;
                }
                System.out.println("POST请求接口信息出错！" + "请求URL:" + url + "==状态码：==" + status + "==返回结果：==" + result);
            } finally {
                response.close();
            }
        } catch (UnsupportedEncodingException e) {
            System.out.println("参数转码错误！" + e);
        } catch (IOException e) {
            System.out.println("获取httpclient错误！" + e);
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                System.out.println("关闭httpclient失败！" + e);
            }
        }
        return null;
    }


    /**
     * 上传文件
     */
    public static String postMultipartResult(String url,Map<String, Object> paramMap,Map<String, Object> headerMap) {
        CloseableHttpClient httpclient = createSSLClientDefault();
        try {
            HttpPost httppost = new HttpPost(url);

            FileBody fileparam = null;
            StringBody stringparam= null;

            // 增加自定义HEADER,注意：使用addHeader而不是setHeader
            if (headerMap != null && !headerMap.isEmpty()) {
                for (String key : headerMap.keySet()) {
                    httppost.addHeader(key, String.valueOf(headerMap.get(key)));
                }
            }
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            if (paramMap != null && !paramMap.isEmpty()) {
                for (String key : paramMap.keySet()) {
                    if(paramMap.get(key).getClass().getName().equals(File.class.getName())){
                        fileparam = new FileBody((File) paramMap.get(key));
                        multipartEntityBuilder.addPart(key,fileparam);
                    }
                    if (paramMap.get(key).getClass().getName().equals(String.class.getName())){
                        stringparam = new StringBody((String) paramMap.get(key),ContentType.TEXT_PLAIN);
                        multipartEntityBuilder.addPart(key,stringparam);
                    }
                   /* paramMap.get(key).getClass().getTypeName()
                    paramList.add(new BasicNameValuePair(key, String.valueOf()));*/
                }
            }

            HttpEntity reqEntity = multipartEntityBuilder.build();

            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000) // 设置请求和传输超时时间
                    .setConnectTimeout(10000).build();
            httppost.setConfig(requestConfig);
            httppost.setEntity(reqEntity);

            System.out.println("executing request " + httppost.getRequestLine());
            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                int status = response.getStatusLine().getStatusCode();

                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "UTF-8");

                // 状态码为200时，才返回正常内容
                if (/*status == HttpStatus.SC_OK && */entity != null) {
                    return result;
                }
                System.out.println("POST请求接口信息出错！" + "请求URL:" + url + "==状态码：==" + status + "==返回结果：==" + result);
            } finally {
                response.close();
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


}
